import { TabToolbarItemSchema } from './../schema/schema';
import { TabPageSchema, TabSchema } from '../schema/schema';
import { ComponentSchema, BuilderHTMLElement, FarrisDesignBaseComponent } from '@farris/designer-element';
import { cloneDeep } from 'lodash-es';
import { ElementPropertyConfig } from '@farris/ide-property-panel';
import { TabProp } from '../property/property-config';
import { RowNode, TreeNode } from '@farris/ui-treetable';
import { TabContextMenuManager } from '../context-menu/context-menu.manager';
import { OperateUtils } from '../../../../utils/operate.utils';
import FdContainerBaseComponent from '../../common/containerBase/containerBase';
import ToolBarComponent from '../../../command/toolbar/component/fd-toolbar';
import FdTabToolBarComponent from './fd-tab-toolbar';
import FdTabPageComponent from './fd-tabpage';
import { FormPropertyChangeObject } from '../../../../entity/property-change-entity';
import { ControlCssLoaderUtils } from '../../../../utils/control-css-loader';
import { DgControl, RefreshFormService } from '@farris/designer-services';
import { ContentContainerSchema } from '../../content-container/schema/schema';
import { SectionSchema } from '../../section/schema/schema';
import dragula from '@farris/designer-dragula';
import { DesignerEnvType } from '@farris/designer-services';

export default class FdTabComponent extends FdContainerBaseComponent {

    private isInFixedContextRules = false;
    /* 标识每个标签页项label的key值 */
    get tabPageLinkKey(): string {
        return `tabNav-${this.key}`;
    }
    /* 标识每个标签页项主体的key值 */
    get tabPageBodyKey(): string {
        return `tabBody-${this.key}`;
    }
    /** 标识当前viewChange的key值 */
    get viewChangeKey(): string {
        return `viewChange-${this.selectedTabPageId}`;
    }

    /** 标签页项实例 */
    private tabPages: FdTabPageComponent[] = [];

    /** 标签页项内部的组件实例 */
    private tabPageComponents: any[];

    /** 当前选中标签页id */
    selectedTabPageId: string;

    /* 标识当前Tab的按钮属性 */
    private toolbarSettings;
    /* 标识当前Tab的扩展属性*/
    private headerExtendSettings;
    /* 存在viewChange扩展时，当前项 */
    private activeTypeItem;
    // 查找ref=form的项
    private formParent = null;
    private multiViewContainerEl = null;
    private toolBarComponent: ToolBarComponent;

    private dragulaBuilder;

    constructor(component: ComponentSchema, options: any) {
        super(component, options);
        // 加载css相关文件
        ControlCssLoaderUtils.loadCss('tabs.css');
        // 增加操作按钮  新增  删除  复制等
        this.customToolbarConfigs = [
            {
                id: 'appendItem',
                title: '新增标签页',
                icon: 'f-icon f-icon-plus-circle text-white',
                click: (e) => {
                    e.stopPropagation();
                    this.appendTabPage();
                }
            }
        ];
    }
    /**
     * 从工具箱拖拽生成的不是Tab，而是Container-Section-Tab三层结构
     */
    static getMetadataInControlBox(targetComponentInstance: FarrisDesignBaseComponent) {
        const radomNum = Math.random().toString().slice(2, 6);

        const tabPageSchema = cloneDeep(TabPageSchema);
        tabPageSchema.id = `tabpage_${radomNum}`;
        tabPageSchema.toolbar.id = `tab_toolbar_${radomNum}`;

        const tabSchema = cloneDeep(TabSchema);
        Object.assign(tabSchema, {
            id: `tab_${radomNum}`,
            appearance: {
                class: 'f-component-tabs f-tabs-has-grid'
            },
            contents: [tabPageSchema],
            selected: tabPageSchema.id
        });

        const sectionSchema = cloneDeep(SectionSchema);
        Object.assign(sectionSchema, {
            id: `section_${radomNum}`,
            appearance: {
                class: 'f-section-tabs f-section-in-mainsubcard'
            },
            fill: false,
            showHeader: false,
            contents: [tabSchema]
        });

        const containerSchema = cloneDeep(ContentContainerSchema);
        Object.assign(containerSchema, {
            id: `container_${radomNum}`,
            appearance: {
                class: 'f-struct-wrapper'
            },
            contents: [sectionSchema]
        });


        // 判断拖拽的目标容器
        const targetComponentSchema = targetComponentInstance.component;
        const targetComponentClassName = (targetComponentSchema && targetComponentSchema.appearance && targetComponentSchema.appearance.class) || '';
        switch (targetComponentSchema && targetComponentSchema.type) {
            case DgControl.ContentContainer.type: {
                // 卡片模板：判断子表是否需要设置为填充
                if (targetComponentSchema.isLikeCardContainer && targetComponentClassName.includes('f-struct-like-card-child-fill')) {
                    containerSchema.appearance.class += ' f-struct-wrapper-child';
                    sectionSchema.fill = true;
                    tabSchema.contentFill = true;
                }
                break;
            }
            case DgControl.Splitter.type: {
                // 左列右卡的模板：修改容器样式
                sectionSchema.appearance.class = 'f-section-tabs f-section-in-main';
                tabSchema.appearance.class = 'f-component-tabs';

                // 左列右卡的模板：判断子表是否需要设置为填充
                const targetSplitterPane = targetComponentInstance.element.querySelector('.f-component-splitter-pane.f-page-child-fill.drag-over');
                if (targetSplitterPane) {
                    containerSchema.appearance.class += ' f-struct-wrapper-child';
                    sectionSchema.fill = true;
                    tabSchema.contentFill = true;
                }

                break;
            }

        }

        return containerSchema;
    }

    // 新增tab页
    appendTabPage() {
        const newTabPage = cloneDeep(TabPageSchema);
        const random = Math.random().toString().slice(2, 6);
        newTabPage.id = `tabpage_${random}`;
        newTabPage.toolbar.id = `tab_toolbar_${random}`;

        this.component.contents.push(newTabPage);
        this.component.currentTabPageInDesignerView = newTabPage.id;

        // 刷新页面，触发控件树更新
        const refreshFormService = this.options.designerHost.getService('RefreshFormService') as RefreshFormService;
        refreshFormService.refreshFormDesigner.next(this.component.id);

    }

    getDefaultSchema(): any {
        return TabSchema;
    }

    getTemplateName(): string {
        return 'Tab';
    }

    init(): void {
        this.components = [];

        this.initTabPageInstances();
    }

    destroy() {
        super.destroy();
        if (this.dragulaBuilder) {
            this.dragulaBuilder.destroy();
            this.dragulaBuilder = null;
        }

    }
    private initTabPageInstances() {
        this.tabPageComponents = [];

        let firstTabPageId = '';
        this.tabPages = [];
        this.component.contents.forEach((tabPage, index) => {
            // 缓存tabPage组件
            const options = Object.assign({}, this.options, { parent: this });
            const tabPageIns = new FdTabPageComponent(tabPage, options);
            this.tabPages.push(tabPageIns);
            this.tabPageComponents[index] = [];
            // initialize empty tabs.
            tabPage.contents = tabPage.contents || [];
            tabPage.contents.forEach(comp => {
                const tabPageComponent: any = this.createComponent(comp, this.options, null);
                this.tabPageComponents[index].push(tabPageComponent);
            });
            firstTabPageId = firstTabPageId ? firstTabPageId : tabPage.id;
        });

        // 将当前选中标签页id记录到DOM结构中，方便组件重绘时定位到上次的TabPage
        this.selectedTabPageId = this.component.currentTabPageInDesignerView || firstTabPageId;
    }

    render(): any {

        // 获取当前tab信息
        this.getToolbarAndExtendSettingsBySelected();

        return super.render(this.renderTemplate('Tab', {
            tabComponents: this.tabPageComponents.map(tabPage => this.renderComponents(tabPage)),
            tabPageLinkKey: this.tabPageLinkKey,
            tabPageBodyKey: this.tabPageBodyKey,
            selectedTabPageId: this.selectedTabPageId,
            // 按钮
            toolbarSettings: this.toolbarSettings,
            // 头部扩展
            headerExtendSettings: this.headerExtendSettings,
            // 获取按钮字符串的方法
            toolBarComponent: this.toolBarComponent,
            // 获取viewChange字符串
            getViewChangeStr: () => this.getViewChangeStr(),
            viewChangeKey: this.viewChangeKey,
        }));
    }



    attach(element: any): any {
        this.loadRefs(element, {
            [this.tabPageLinkKey]: 'multiple',
            [this.tabPageBodyKey]: 'multiple',
            [this.viewChangeKey]: 'single',
        });

        const superAttach: any = super.attach(element);

        // 注册标签页切换事件
        this.refs[this.tabPageLinkKey].forEach((tabLink, index) => {

            this.addEventListener(tabLink, 'click', (event) => {
                event.preventDefault();
                event.stopPropagation();
                const taPageId = tabLink.getAttribute('id');
                const currentIndex = this.component.contents.findIndex(c => c.id === taPageId);
                this.setTabPage(currentIndex, event);

            });
            this.tabPages[index].attach(tabLink);
        });
        // 头部扩展配置 viewChange
        if (this.headerExtendSettings) {
            // 绑定
            if (this.headerExtendSettings.viewType == 'tile') {
                OperateUtils.bindTileEventForViewChange((obj, type, func) => { this.addEventListener(obj, type, func) }, this.headerExtendSettings.toolbarData, this.activeTypeItem, this.refs[this.viewChangeKey], () => {
                    this.findMultiViewContainerEl()
                    return { multiViewContainerEl: this.multiViewContainerEl };
                }, (returnActiveItem) => {
                    this.activeTypeItem = returnActiveItem;
                    // 当前结构上保存
                    this.headerExtendSettings['currentTypeInDesignerView'] = this.activeTypeItem['type'];
                    // 通过DOM操作更新viewchange
                    OperateUtils.updateTileByActiveType('tile', this.activeTypeItem, this.refs[this.viewChangeKey]);
                });

            } else if (this.headerExtendSettings.viewType == 'dropdown') {
                OperateUtils.bindDropdownEventForViewChange((obj, type, func) => { this.addEventListener(obj, type, func) }, this.headerExtendSettings.toolbarData, this.activeTypeItem, this.refs[this.viewChangeKey], () => {
                    this.findMultiViewContainerEl()
                    return { multiViewContainerEl: this.multiViewContainerEl };
                }, (returnActiveItem) => {
                    this.activeTypeItem = returnActiveItem;
                    // 当前结构上保存
                    this.headerExtendSettings['currentTypeInDesignerView'] = this.activeTypeItem['type'];
                    // 通过DOM操作更新viewchange
                    OperateUtils.updateTileByActiveType('dropdown', this.activeTypeItem, this.refs[this.viewChangeKey]);
                });
            }
        }

        // 加载子组件
        this.refs[this.tabPageBodyKey].forEach((tab, index) => {
            this.attachComponents(tab, this.tabPageComponents[index], this.component.contents[index].contents);
        });
        // 工具栏按钮绑定事件
        const tabToolBarEle = element.querySelector('.farris-component-TabToolbar');
        if (tabToolBarEle && this.toolBarComponent) {
            this.toolBarComponent.attach(tabToolBarEle);
        }

        // 监听HeaderNav区域横向滚动条事件，用于改变选中标签页的图标位置
        const navTabPanel = this.element.querySelector('.farris-nav-tabs') as HTMLElement;
        if (navTabPanel) {
            this.setPositionOfBtnGroupWhenHScroll(navTabPanel);
        }

        // 设置横向滚动条位置
        this.setHorizontalScrollbarPosition();

        this.initDragula();

        this.registerTabBodyScrollEvent();
        return superAttach;
    }

    /**
     * 横向滚动滚动条时计算工具栏位置
     * @param element 监听滚动的元素
     */
    private setPositionOfBtnGroupWhenHScroll(element) {
        this.addEventListener(element, 'scroll', (e) => {
            const selectDom = (e.target as any).querySelector('.dgComponentSelected');
            if (selectDom) {
                const toolbar = selectDom.querySelector('.component-btn-group');
                if (this.isNavElementInViewport(selectDom, e.target)) {
                    this.setPositionOfBtnGroupInHeader(selectDom);
                } else {
                    if (toolbar) {
                        toolbar.style.display = 'none';
                    }
                }
            }
        });
    }

    /**
     * 判断标签页是否在可视化区域内
     * @param navEle 单个标签页nav div
     * @param navTabsEle  整个标签页nav div的父级
     */
    private isNavElementInViewport(navEle, navTabsEle) {

        const container = navTabsEle.getBoundingClientRect();
        const box = navEle.getBoundingClientRect();

        const isRightInView = (box.left + box.width) <= (container.left + container.width)

        const isLeftInView = (box.left + box.width) >= container.left;

        return isRightInView && isLeftInView;
    }
    /**
     * 计算工具栏位置
     * @param tabNavEle 工具栏父级
     */
    private setPositionOfBtnGroupInHeader(tabNavEle) {
        const toolbar = tabNavEle.querySelector('.component-btn-group') as HTMLElement;
        if (toolbar) {
            toolbar.style.display = '';
            const p = toolbar.getBoundingClientRect();
            toolbar.querySelector('div').style.left = (p.left - 26) + 'px';
        }
    }
    /**
     * 监听tab-body的滚动事件
     */
    private registerTabBodyScrollEvent() {
        // 在tab填充的场景下，滚动条会出现在tab-body上，所以需要监听tab-body的滚动事件，用于重新计算选中控件操作按钮的位置
        const tabBodyPanels = this.element.querySelectorAll('.farris-tabs-body') as NodeListOf<HTMLElement>;
        if (tabBodyPanels && tabBodyPanels.length) {
            tabBodyPanels.forEach(tabBody => {
                this.bindingScrollEvent(tabBody);
            });
        }
    }


    /**
     * 切换标签页
     * @param index 标签页索引
     */
    private setTabPage(index: number, e) {
        if (
            !this.tabPageComponents ||
            !this.tabPageComponents[index] ||
            !this.refs[this.tabPageBodyKey] ||
            !this.refs[this.tabPageBodyKey][index]
        ) {
            return;
        }
        const selectedTabId = this.component.contents[index].id;

        this.selectedTabPageId = selectedTabId;
        this.component.currentTabPageInDesignerView = this.selectedTabPageId;
        // 获取当前tab信息
        this.getToolbarAndExtendSettingsBySelected();

        // 若是在控件树上点击标签页项，需要提前通知设计器标签页项的实例，否则无法切换代码编辑器内的代码
        if (!e) {
            this.emit('componentClicked', { e, componentInstance: this.tabPages[index] });
        }

        // 触发重绘
        this.redraw().then(() => {

            // 触发选中单个标签页
            this.tabPages[index].triggerComponentClicked(e);
        });


    }

    /**
     * 设置横向滚动条位置
     */
    private setHorizontalScrollbarPosition() {

        const targetNavEle = this.element.querySelector('.f-state-active');
        if (targetNavEle) {
            // 设置横向滚动条位置
            const targetNavEleRect = targetNavEle.getBoundingClientRect();
            const containerEleRect = targetNavEle.parentElement.getBoundingClientRect();
            this.element.querySelector('.farris-nav-tabs').scrollLeft = targetNavEleRect.left - containerEleRect.left;

            // 计算工具栏位置
            this.setPositionOfBtnGroupInHeader(targetNavEle);
        }
    }

    /**
     * 根据当前Tab 确定按钮和扩展区域
     */
    private getToolbarAndExtendSettingsBySelected(selectedId = '') {
        selectedId = selectedId ? selectedId : this.selectedTabPageId;
        let selectedTab = null;
        this.component.contents.forEach(tab => {
            if (tab.id === selectedId) {
                selectedTab = tab;
            }
        });
        if (!selectedTab) {
            selectedTab = this.component.contents[0];
        }
        if (selectedTab) {
            if (selectedTab.toolbar && selectedTab.toolbar.contents && selectedTab.toolbar.contents.length > 0) {
                this.toolbarSettings = selectedTab.toolbar;
            } else {
                this.toolbarSettings = null;
            }
            if (selectedTab.multiViews && selectedTab.views && selectedTab.views.toolbarData && selectedTab.views.toolbarData.length > 0) {
                this.headerExtendSettings = selectedTab.views;
                this.activeTypeItem = OperateUtils.viewChangeInitActiveItem(this.headerExtendSettings['currentTypeInDesignerView'] || this.headerExtendSettings['defaultType'], this.activeTypeItem, this.headerExtendSettings.toolbarData);
            } else {
                this.headerExtendSettings = null;
            }
            this.formParent = null;
            this.multiViewContainerEl = null;
        } else {
            this.toolbarSettings = null;
        }
        if (this.toolbarSettings) {
            // 新建当前工具栏按钮实例并渲染
            const options = Object.assign({}, this.options, { parent: this, parentTabPge: selectedTab });
            this.toolBarComponent = new FdTabToolBarComponent(this.toolbarSettings, options);
            this.toolBarComponent.init();
        }


    }
    /**
     * 组装属性面板配置数据
     */
    getPropertyConfig(): ElementPropertyConfig[] {
        const serviceHost = this.options.designerHost;
        const prop: TabProp = new TabProp(serviceHost, this.viewModelId, this.componentId);
        const propertyConfig: ElementPropertyConfig[] = prop.getPropConfig(this.component);
        return propertyConfig;
    }

    /**
     * 组装右键菜单
     * @param rowNode 组件在控件树上对应的行数据
     */
    resolveContextMenuConfig(rowNode: RowNode, parentRowNode: RowNode) {
        const menuManager = new TabContextMenuManager(this, rowNode, parentRowNode);
        return menuManager.setContextMenuConfig();
    }

    private getViewChangeStr() {
        return OperateUtils.getViewChangeStr(this.headerExtendSettings.toolbarData, this.headerExtendSettings.viewType, this.activeTypeItem);
    }
    /**
     * 查找multiViewContainerEl
     */
    private findMultiViewContainerEl() {
        if (this.multiViewContainerEl) {
            return;
        }
        if (!this.formParent) {
            this.formParent = OperateUtils.getFormParent(this.element);
        }
        if (this.formParent && !this.multiViewContainerEl) {
            // 查找同组的元素
            this.multiViewContainerEl = this.formParent.querySelector('.farris-component-MultiViewContainer[viewchange=' + this.headerExtendSettings.viewGroupIdentify + ']');
        }
    }
    /**
     * 判断拖拽接收控件的范围
     * @param sourceElement 源控件
     * @param targetElement 目标控件
     */
    canAccepts(sourceElement: BuilderHTMLElement, targetElement: BuilderHTMLElement): boolean {

        const canAccepts = super.canAccepts(sourceElement, targetElement);

        if (!canAccepts) {
            return false;
        }
        // 限定只有空的tabPage可以接收控件
        let targetElementId = targetElement.getAttribute('id');
        if (targetElementId && targetElementId.includes('-body')) {
            targetElementId = targetElementId.replace('-body', '');
        }
        const targetTabPage = this.component.contents.find(c => c.id === targetElementId);
        if (!targetTabPage || !targetTabPage.contents || targetTabPage.contents.length !== 0) {
            return false;
        }
        return true;
    }

    /**
     * 由外部触发组件内部的点击事件：在控件树上点击某一TabPage时，触发tab的切换事件
     * @param treeNode 控件树节点
     */
    triggerComponentInsideClick(treeNode: TreeNode) {

        if (!treeNode.id) {
            return;
        }
        // 1、切换不同的标签页
        const index = this.component.contents.findIndex(c => c.id === treeNode.id);
        if (treeNode.id !== this.selectedTabPageId) {
            this.setTabPage(index, null);
            return;
        }

        // 2、同一个标签页，而且当前tabPage没有选中状态
        const currentTabPage = this.tabPages.find(tab => tab.id === this.selectedTabPageId);
        if (!currentTabPage || !currentTabPage.element) {
            return;
        }
        if (!currentTabPage.element.className.includes('dgComponentSelected')) {
            // 显示边框、切换属性面板
            currentTabPage.triggerComponentClicked(null);

        }

    }

    /**
     * 属性变更后事件：默认监听样式类属性变更，并触发模板重绘
     * @param changeObject 变更集
     * @param propertyIDs 需要额外监听的属性ID列表
     */
    onPropertyChanged(changeObject: FormPropertyChangeObject): void {

        if (['titleWidth', 'autoTitleWidth', 'contentFill'].includes(changeObject.propertyID)) {
            // 触发标签页整体重绘
            this.redraw();
        }


        if (['title', 'position', 'headerTemplate'].includes(changeObject.propertyID)) {
            // 触发页面重绘
            this.redraw().then(() => {

                // 触发当前选中标签页项的重绘
                if (this.selectedTabPageId && this.tabPages) {
                    const currentTabPage = this.tabPages.find(t => t.id === this.selectedTabPageId);
                    currentTabPage.triggerComponentClick();

                    const targetNavEle = this.element.querySelector('.f-state-active');
                    this.setPositionOfBtnGroupInHeader(targetNavEle);
                }
            });
        }

    }

    /**
     * 判断在可视化区域中是否隐藏容器间距和线条
     */
    hideNestedPaddingInDesginerView() {
        // 控件本身样式
        const cmpClass = this.component.appearance && this.component.appearance.class || '';
        const cmpClassList = cmpClass ? cmpClass.split(' ') : [];

        // 父级节点
        const parent = this.parent && this.parent.component;
        const parentClass = parent && parent.appearance && parent.appearance.class || '';
        const parentClassList = parentClass ? parentClass.split(' ') : [];

        const grandParent = this.parent && this.parent.parent && this.parent.parent.component;
        const grandParentClass = grandParent && grandParent.appearance && grandParent.appearance.class || '';
        const grandParentClassList = grandParentClass ? grandParentClass.split(' ') : [];

        // 1、子表区域固定层级：detail-container(f-struct-wrapper)--->detail-section(f-section-tabs)--->detail-tab(f-component-tabs)
        if (cmpClassList.includes('f-component-tabs') && parentClassList.includes('f-section-tabs') && grandParentClassList.includes('f-struct-wrapper')) {
            this.isInFixedContextRules = true;
            return true;
        }

    }

    checkCanMoveComponent(): boolean {
        return !this.isInFixedContextRules;
    }

    checkCanDeleteComponent(): boolean {
        return !this.isInFixedContextRules;
    }

    /**
     * 初始化拖拽：支持标签页交换顺序
     */
    initDragula() {
        if (this.dragulaBuilder) {
            this.dragulaBuilder.destroy();
        }

        if (!dragula) {
            return;
        }
        const navsElement = this.element.querySelector('.farris-nav-tabs');
        if (!navsElement || !this.refs[this.tabPageLinkKey] || this.refs[this.tabPageLinkKey].length === 0) {
            return;
        }
        this.dragulaBuilder = dragula([navsElement], {
            mirrorContainer: navsElement,   // 镜像容器
            direction: 'horizontal'
        })
            .on('drop', (element, target) => this.onDrop(element, target))
            .on('dragend', () => this.dragEnd());
    }
    /**
     * 拖拽放开事件
     * @param element 被拖拽的元素
     * @param target 目标区域
     */
    private onDrop(element: BuilderHTMLElement, target: BuilderHTMLElement) {

        const taPageId = element.getAttribute('id');
        const targetIndex = Array.from(target.children).findIndex(e => e.getAttribute('id') === taPageId);
        const sourceIndex = this.component.contents.findIndex(c => c.id === taPageId);
        const sourceTabPage = this.component.contents[sourceIndex];
        if (sourceIndex !== targetIndex && sourceIndex > -1 && targetIndex > -1) {
            // 更新DOM结构
            this.component.contents.splice(sourceIndex, 1);
            this.component.contents.splice(targetIndex, 0, sourceTabPage);

            // 因为标签页位置变化，需要重新组装tabPage实例和tabPage内部组件的实例，以便于后续通过index取值和取实例
            const sourceTabPageInstance = this.tabPages[sourceIndex];
            this.tabPages.splice(sourceIndex, 1);
            this.tabPages.splice(targetIndex, 0, sourceTabPageInstance);

            const sourceTabPageCmps = this.tabPageComponents[sourceIndex];
            this.tabPageComponents.splice(sourceIndex, 1);
            this.tabPageComponents.splice(targetIndex, 0, sourceTabPageCmps);

        }
    }

    /**
     * 拖拽结束事件
     */
    private dragEnd() {
        // 重新计算标签页操作按钮的位置
        const targetNavEle = this.element.querySelector('.f-state-active');
        if (targetNavEle) {
            this.setPositionOfBtnGroupInHeader(targetNavEle);
        }

        //  触发控件树刷新
        const refreshService = this.options.designerHost.getService('RefreshFormService') as RefreshFormService;
        refreshService.refreshControlTree.next();
    }
}
